home *** CD-ROM | disk | FTP | other *** search
-
- #include "StdSet.h"
- #include <Types.h>
- #include <Memory.h>
- #include <ToolUtils.h>
- #include <OSUtils.h>
- #include <StdDef.h>
- #include <StdLib.h>
- #include <String.h>
- #include <Errors.h>
-
- /* File StdSet.c
- operations for sets of long integers or pointers, implementation.
- Copyright (c) 1996, 1997 by John Montbriand. All Rights Reserved.
- Permission hereby granted for public use.
- Distribute freely in areas where the laws of copyright apply.
- USE AT YOUR OWN RISK.
- DO NOT DISTRIBUTE MODIFIED COPIES.
- Comments/questions/postcards* to the author at the address:
- John Montbriand
- P.O. Box. 1133
- Saskatoon Saskatchewan Canada
- S7K 3N2
- or by email at:
- tinyjohn@sk.sympatico.ca
- *if you mail a postcard, then I will provide you with technical support
- regarding questions you may have about this file.
- see also: <http://www3.sk.sympatico.ca/tinyjohn>
- */
-
-
- #define kSetBufSz 64
-
- static Boolean rSetSearch(TSETELT* list, TSETELT key, long first, long last, long* where) {
- if (last < first) {
- *where = first;
- return false;
- } else {
- long mid = (first + last) / 2;
- TSETELT midval = list[mid];
- if (key == midval) {
- *where = mid;
- return true;
- } else if (key > midval)
- return rSetSearch(list, key, mid + 1, last, where);
- else return rSetSearch(list, key, first, mid - 1, where);
- }
- }
-
- static Boolean SetSearch(SetHandle set, TSETELT key, long* where) {
- return rSetSearch((*set)->elt, key, 0, (*set)->n - 1, where);
- }
-
- SetHandle NewSet(void) {
- return (SetHandle) NewHandleClear(offsetof(SetRecord, elt));
- }
-
- void ClearSet(SetHandle set) {
- SetHandleSize((Handle) set, offsetof(SetRecord, elt));
- (**set).n = 0;
- }
-
-
- static int SetEltCompare(const void *a, const void *b) {
- return (* (TSETELT*) a) - (* (TSETELT*) b);
- }
-
- SetHandle BuildSet(long count, TSETELT *data) {
- SetHandle set;
- TSETELT *srcp;
- long i;
- if ((set = NewSet()) == NULL) return NULL;
- for (srcp = data, i=0; i<count; i++)
- if (!SetAddElt(set, *srcp++)) {
- DisposeSet(set);
- return NULL;
- }
- return set;
- }
-
- void DisposeSet(SetHandle set) {
- DisposeHandle((Handle) set);
- }
-
- Boolean SetCopy(SetHandle dst, SetHandle src) {
- long bytes;
- bytes = GetHandleSize((Handle) src);
- SetHandleSize((Handle) dst, bytes);
- if (MemError() != noErr) return false;
- BlockMoveData(*src, *dst, bytes);
- return true;
- }
-
- Boolean SetAddElt(SetHandle set, TSETELT value) {
- long where, i;
- SetRecord *sp;
- if (SetSearch(set, value, &where)) return true;
- SetHandleSize((Handle) set, offsetof(SetRecord, elt) + ((*set)->n + 1)*sizeof(TSETELT));
- if (MemError() != noErr) return false;
- sp = *set;
- sp->n += 1;
- for (i = sp->n - 1; i > where; i--) sp->elt[i] = sp->elt[i-1];
- sp->elt[where] = value;
- return true;
- }
-
- void SetRemoveElt(SetHandle set, TSETELT value) {
- long where;
- if (SetSearch(set, value, &where)) {
- Munger((Handle) set,
- offsetof(SetRecord, elt) + where*sizeof(TSETELT),
- NULL, sizeof(TSETELT), &value, 0);
- (*set)->n -= 1;
- }
- }
-
- Boolean SetEmpty(SetHandle a) {
- return ((*a)->n == 0);
- }
-
- Boolean SetEqual(SetHandle a, SetHandle b) {
- TSETELT *vala, *valb, *enda, *endb;
- enda = (vala = (*a)->elt) + (*a)->n;
- endb = (valb = (*b)->elt) + (*b)->n;
- while (vala < enda && valb < endb)
- if (*vala++ != *valb++) return false;
- return (vala == enda && valb == endb);
- }
-
- Boolean SetSubset(SetHandle a, SetHandle b) {
- TSETELT *vala, *valb, *enda, *endb;
- enda = (vala = (*a)->elt) + (*a)->n;
- endb = (valb = (*b)->elt) + (*b)->n;
- while (vala < enda && valb < endb) {
- if (*vala == *valb) {
- vala++;
- valb++;
- } else if (*vala < *valb)
- vala++;
- else return false;
- }
- if ((*a)->n == 0)
- return ((*b)->n == 0); // empty set is subset of empty set
- else return true;
- }
-
- Boolean SetMember(SetHandle a, TSETELT value) {
- long where;
- return SetSearch(a, value, &where);
- }
-
- SetHandle SetAnd(SetHandle a, SetHandle b) {
- TSETELT *vala, *valb, *enda, *endb;
- SetHandle c;
- TSETELT bufferp[kSetBufSz], *putp;
- long count;
- OSErr err;
- putp = bufferp;
- if ((c = NewSet()) == NULL) return NULL;
- HLock((Handle) a);
- HLock((Handle) b);
- enda = (vala = (*a)->elt) + (*a)->n;
- endb = (valb = (*b)->elt) + (*b)->n;
- while (vala < enda && valb < endb) {
- if (*vala == *valb) {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *vala++;
- valb++;
- } else if (*vala < *valb) vala++; else valb++;
- }
- if ((count = putp - bufferp) > 0) {
- err = PtrAndHand(bufferp, (Handle) c, count*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += count;
- }
- HUnlock((Handle) a);
- HUnlock((Handle) b);
- return c;
- bail:
- HUnlock((Handle) a);
- HUnlock((Handle) b);
- DisposeHandle((Handle) c);
- return NULL;
- }
-
- SetHandle SetOr(SetHandle a, SetHandle b) {
- TSETELT *vala, *valb, *enda, *endb;
- SetHandle c;
- TSETELT bufferp[kSetBufSz], *putp;
- long count;
- OSErr err;
- putp = bufferp;
- if ((c = NewSet()) == NULL) return NULL;
- HLock((Handle) a);
- HLock((Handle) b);
- enda = (vala = (*a)->elt) + (*a)->n;
- endb = (valb = (*b)->elt) + (*b)->n;
- while (vala < enda && valb < endb) {
- if (*vala == *valb) {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *vala++;
- valb++;
- } else if (*vala < *valb) {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *vala++;
- } else {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *valb++;
- }
- }
- while (vala < enda) {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *vala++;
- }
- while (valb < endb) {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *valb++;
- }
- if ((count = putp - bufferp) > 0) {
- err = PtrAndHand(bufferp, (Handle) c, count*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += count;
- }
- HUnlock((Handle) a);
- HUnlock((Handle) b);
- return c;
- bail:
- HUnlock((Handle) a);
- HUnlock((Handle) b);
- DisposeHandle((Handle) c);
- return NULL;
- }
-
- SetHandle SetXor(SetHandle a, SetHandle b) {
- TSETELT *vala, *valb, *enda, *endb;
- SetHandle c;
- TSETELT bufferp[kSetBufSz], *putp;
- long count;
- OSErr err;
- putp = bufferp;
- if ((c = NewSet()) == NULL) return NULL;
- HLock((Handle) a);
- HLock((Handle) b);
- enda = (vala = (*a)->elt) + (*a)->n;
- endb = (valb = (*b)->elt) + (*b)->n;
- while (vala < enda && valb < endb) {
- if (*vala == *valb) {
- vala++;
- valb++;
- } else if (*vala < *valb) {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *vala++;
- } else {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *valb++;
- }
- }
- while (vala < enda) {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *vala++;
- }
- while (valb < endb) {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *valb++;
- }
- if ((count = putp - bufferp) > 0) {
- err = PtrAndHand(bufferp, (Handle) c, count*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += count;
- }
- HUnlock((Handle) a);
- HUnlock((Handle) b);
- return c;
- bail:
- HUnlock((Handle) a);
- HUnlock((Handle) b);
- DisposeHandle((Handle) c);
- return NULL;
- }
-
- SetHandle SetRemove(SetHandle a, SetHandle b) {
- TSETELT *vala, *valb, *enda, *endb;
- SetHandle c;
- TSETELT bufferp[kSetBufSz], *putp;
- long count;
- OSErr err;
- putp = bufferp;
- if ((c = NewSet()) == NULL) return NULL;
- HLock((Handle) a);
- HLock((Handle) b);
- enda = (vala = (*a)->elt) + (*a)->n;
- endb = (valb = (*b)->elt) + (*b)->n;
- while (vala < enda && valb < endb) {
- if (*vala == *valb) {
- vala++;
- valb++;
- } else if (*vala < *valb) {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *vala++;
- } else valb++;
- }
- while (vala < enda) {
- if (putp - bufferp == kSetBufSz) {
- err = PtrAndHand(bufferp, (Handle) c, kSetBufSz*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += kSetBufSz;
- putp = bufferp;
- }
- *putp++ = *vala++;
- }
- if ((count = putp - bufferp) > 0) {
- err = PtrAndHand(bufferp, (Handle) c, count*sizeof(TSETELT));
- if (err != noErr) goto bail;
- (*c)->n += count;
- }
- HUnlock((Handle) a);
- HUnlock((Handle) b);
- return c;
- bail:
- HUnlock((Handle) a);
- HUnlock((Handle) b);
- DisposeHandle((Handle) c);
- return NULL;
- }
-
-
- long SetCard(SetHandle a) {
- return (*a)->n;
- }
-
- TSETELT SetElement(SetHandle a, long index) {
- return (*a)->elt[index];
- }
-
- static int SetCompareCard(const void *a, const void *b) {
- long carda, cardb, i;
- SetHandle lsa, lsb;
- TSETELT elta, eltb;
- /* check for NULL sets */
- if (a == NULL && b == NULL)
- return 0;
- else if (a == NULL && b != NULL)
- return -1;
- else if (a != NULL && b == NULL)
- return 1;
- /* compare the sets */
- lsa = * (SetHandle*) a;
- lsb = * (SetHandle*) b;
- carda = SetCard(lsa);
- cardb = SetCard(lsb);
- if (carda == cardb && carda > 0) {
- for (i=0; i<carda;i++) {
- elta = SetElement(lsa, i);
- eltb = SetElement(lsb, i);
- if (elta != eltb) return (elta - eltb);
- }
- return 0;
- } else return carda - cardb;
- }
- typedef Boolean (*PowerSetFilter)(SetHandle a);
-
- PowerSet GeneratePowerSet(SetHandle a) {
- long n, i, j, next, count;
- TSETELT item;
- PowerSet powerset;
- SetHandle *psp;
- if ((*a)->n > 24) return NULL;
- n = 1;
- count = 1 << (*a)->n;
- powerset = (PowerSet) NewHandleClear(count * sizeof(long));
- if (powerset == NULL) return NULL;
- HLock((Handle) powerset);
- psp = *powerset;
- for (i=0; i < count; i++)
- if ((psp[i] = NewSet()) == NULL) goto bail;
- for (i=0; i < (*a)->n; i++) {
- item = SetElement(a, i);
- for (j=0, next=n; j< n; j++, next++) {
- SetCopy(psp[next], psp[j]);
- if (!SetAddElt(psp[next], item)) goto bail;
- }
- n = next;
- }
- qsort(psp, count, sizeof(SetHandle), SetCompareCard);
- HUnlock((Handle) powerset);
- return powerset;
- bail:
- if (powerset != NULL) {
- for (i=0; i < count; i++) if (psp[i] != NULL)
- DisposeSet(psp[i]);
- DisposeHandle((Handle) powerset);
- }
- return NULL;
- }
-
- void DisposePowerSet(PowerSet powerset) {
- SetHandle *psp;
- long i, count;
- count = GetHandleSize((Handle) powerset) / sizeof(SetHandle);
- HLock((Handle) powerset);
- psp = *powerset;
- for (i=0; i < count; i++) if (psp[i] != NULL)
- DisposeSet(psp[i]);
- DisposeHandle((Handle) powerset);
- }
-
- SetHandle PowerSetElt(PowerSet powerset, long index) {
- return (*powerset)[index];
- }
-
- long PowerSetSize(PowerSet powerset) {
- return GetHandleSize((Handle) powerset) / sizeof(SetHandle);
- }
-
-
- static Boolean rSetPermute(TSETELT* elts, long nelts, long rotcount, SetPermutation perm, long param) {
- if (rotcount == 1)
- return perm(elts, nelts, param);
- else {
- long i;
- for (i=0; i<rotcount; i++) {
- TSETELT savelast;
- if (!rSetPermute(elts, nelts, rotcount-1, perm, param)) return false;
- savelast = elts[rotcount-1];
- memmove(elts+1, elts, (rotcount-1)*sizeof(TSETELT));
- elts[0] = savelast;
- }
- return true;
- }
- }
-
- OSErr SetPermute(SetHandle a, SetPermutation perm, long param) {
- long n, i;
- OSErr err;
- TSETELT *locallist;
- locallist = NULL;
- if ((n = SetCard(a)) == 0) return paramErr;
- locallist = (TSETELT *) NewPtr(sizeof(TSETELT) * n);
- if ((err = MemError()) != noErr) return err;
- for (i=0; i<n; i++) locallist[i] = (**a).elt[i];
- rSetPermute(locallist, n, n, perm, param);
- DisposePtr((Ptr) locallist);
- return noErr;
- }
-
-
-